home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / SimpleXMLRPCServer.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  17KB  |  485 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''Simple XML-RPC Server.
  5.  
  6. This module can be used to create simple XML-RPC servers
  7. by creating a server and either installing functions, a
  8. class instance, or by extending the SimpleXMLRPCServer
  9. class.
  10.  
  11. It can also be used to handle XML-RPC requests in a CGI
  12. environment using CGIXMLRPCRequestHandler.
  13.  
  14. A list of possible usage patterns follows:
  15.  
  16. 1. Install functions:
  17.  
  18. server = SimpleXMLRPCServer(("localhost", 8000))
  19. server.register_function(pow)
  20. server.register_function(lambda x,y: x+y, \'add\')
  21. server.serve_forever()
  22.  
  23. 2. Install an instance:
  24.  
  25. class MyFuncs:
  26.     def __init__(self):
  27.         # make all of the string functions available through
  28.         # string.func_name
  29.         import string
  30.         self.string = string
  31.     def _listMethods(self):
  32.         # implement this method so that system.listMethods
  33.         # knows to advertise the strings methods
  34.         return list_public_methods(self) +                 [\'string.\' + method for method in list_public_methods(self.string)]
  35.     def pow(self, x, y): return pow(x, y)
  36.     def add(self, x, y) : return x + y
  37.  
  38. server = SimpleXMLRPCServer(("localhost", 8000))
  39. server.register_introspection_functions()
  40. server.register_instance(MyFuncs())
  41. server.serve_forever()
  42.  
  43. 3. Install an instance with custom dispatch method:
  44.  
  45. class Math:
  46.     def _listMethods(self):
  47.         # this method must be present for system.listMethods
  48.         # to work
  49.         return [\'add\', \'pow\']
  50.     def _methodHelp(self, method):
  51.         # this method must be present for system.methodHelp
  52.         # to work
  53.         if method == \'add\':
  54.             return "add(2,3) => 5"
  55.         elif method == \'pow\':
  56.             return "pow(x, y[, z]) => number"
  57.         else:
  58.             # By convention, return empty
  59.             # string if no help is available
  60.             return ""
  61.     def _dispatch(self, method, params):
  62.         if method == \'pow\':
  63.             return pow(*params)
  64.         elif method == \'add\':
  65.             return params[0] + params[1]
  66.         else:
  67.             raise \'bad method\'
  68.  
  69. server = SimpleXMLRPCServer(("localhost", 8000))
  70. server.register_introspection_functions()
  71. server.register_instance(Math())
  72. server.serve_forever()
  73.  
  74. 4. Subclass SimpleXMLRPCServer:
  75.  
  76. class MathServer(SimpleXMLRPCServer):
  77.     def _dispatch(self, method, params):
  78.         try:
  79.             # We are forcing the \'export_\' prefix on methods that are
  80.             # callable through XML-RPC to prevent potential security
  81.             # problems
  82.             func = getattr(self, \'export_\' + method)
  83.         except AttributeError:
  84.             raise Exception(\'method "%s" is not supported\' % method)
  85.         else:
  86.             return func(*params)
  87.  
  88.     def export_add(self, x, y):
  89.         return x + y
  90.  
  91. server = MathServer(("localhost", 8000))
  92. server.serve_forever()
  93.  
  94. 5. CGI script:
  95.  
  96. server = CGIXMLRPCRequestHandler()
  97. server.register_function(pow)
  98. server.handle_request()
  99. '''
  100. import xmlrpclib
  101. from xmlrpclib import Fault
  102. import SocketServer
  103. import BaseHTTPServer
  104. import sys
  105. import os
  106.  
  107. def resolve_dotted_attribute(obj, attr, allow_dotted_names = True):
  108.     """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d
  109.  
  110.     Resolves a dotted attribute name to an object.  Raises
  111.     an AttributeError if any attribute in the chain starts with a '_'.
  112.  
  113.     If the optional allow_dotted_names argument is false, dots are not
  114.     supported and this function operates similar to getattr(obj, attr).
  115.     """
  116.     if allow_dotted_names:
  117.         attrs = attr.split('.')
  118.     else:
  119.         attrs = [
  120.             attr]
  121.     for i in attrs:
  122.         if i.startswith('_'):
  123.             raise AttributeError('attempt to access private attribute "%s"' % i)
  124.             continue
  125.         obj = getattr(obj, i)
  126.     
  127.     return obj
  128.  
  129.  
  130. def list_public_methods(obj):
  131.     '''Returns a list of attribute strings, found in the specified
  132.     object, which represent callable attributes'''
  133.     return _[1]
  134.  
  135.  
  136. def remove_duplicates(lst):
  137.     '''remove_duplicates([2,2,2,1,3,3]) => [3,1,2]
  138.  
  139.     Returns a copy of a list without duplicates. Every list
  140.     item must be hashable and the order of the items in the
  141.     resulting list is not defined.
  142.     '''
  143.     u = { }
  144.     for x in lst:
  145.         u[x] = 1
  146.     
  147.     return u.keys()
  148.  
  149.  
  150. class SimpleXMLRPCDispatcher:
  151.     '''Mix-in class that dispatches XML-RPC requests.
  152.  
  153.     This class is used to register XML-RPC method handlers
  154.     and then to dispatch them. There should never be any
  155.     reason to instantiate this class directly.
  156.     '''
  157.     
  158.     def __init__(self):
  159.         self.funcs = { }
  160.         self.instance = None
  161.  
  162.     
  163.     def register_instance(self, instance, allow_dotted_names = False):
  164.         """Registers an instance to respond to XML-RPC requests.
  165.  
  166.         Only one instance can be installed at a time.
  167.  
  168.         If the registered instance has a _dispatch method then that
  169.         method will be called with the name of the XML-RPC method and
  170.         its parameters as a tuple
  171.         e.g. instance._dispatch('add',(2,3))
  172.  
  173.         If the registered instance does not have a _dispatch method
  174.         then the instance will be searched to find a matching method
  175.         and, if found, will be called. Methods beginning with an '_'
  176.         are considered private and will not be called by
  177.         SimpleXMLRPCServer.
  178.  
  179.         If a registered function matches a XML-RPC request, then it
  180.         will be called instead of the registered instance.
  181.  
  182.         If the optional allow_dotted_names argument is true and the
  183.         instance does not have a _dispatch method, method names
  184.         containing dots are supported and resolved, as long as none of
  185.         the name segments start with an '_'.
  186.  
  187.             *** SECURITY WARNING: ***
  188.  
  189.             Enabling the allow_dotted_names options allows intruders
  190.             to access your module's global variables and may allow
  191.             intruders to execute arbitrary code on your machine.  Only
  192.             use this option on a secure, closed network.
  193.  
  194.         """
  195.         self.instance = instance
  196.         self.allow_dotted_names = allow_dotted_names
  197.  
  198.     
  199.     def register_function(self, function, name = None):
  200.         '''Registers a function to respond to XML-RPC requests.
  201.  
  202.         The optional name argument can be used to set a Unicode name
  203.         for the function.
  204.         '''
  205.         if name is None:
  206.             name = function.__name__
  207.         
  208.         self.funcs[name] = function
  209.  
  210.     
  211.     def register_introspection_functions(self):
  212.         '''Registers the XML-RPC introspection methods in the system
  213.         namespace.
  214.  
  215.         see http://xmlrpc.usefulinc.com/doc/reserved.html
  216.         '''
  217.         self.funcs.update({
  218.             'system.listMethods': self.system_listMethods,
  219.             'system.methodSignature': self.system_methodSignature,
  220.             'system.methodHelp': self.system_methodHelp })
  221.  
  222.     
  223.     def register_multicall_functions(self):
  224.         '''Registers the XML-RPC multicall method in the system
  225.         namespace.
  226.  
  227.         see http://www.xmlrpc.com/discuss/msgReader$1208'''
  228.         self.funcs.update({
  229.             'system.multicall': self.system_multicall })
  230.  
  231.     
  232.     def _marshaled_dispatch(self, data, dispatch_method = None):
  233.         '''Dispatches an XML-RPC method from marshalled (XML) data.
  234.  
  235.         XML-RPC methods are dispatched from the marshalled (XML) data
  236.         using the _dispatch method and the result is returned as
  237.         marshalled data. For backwards compatibility, a dispatch
  238.         function can be provided as an argument (see comment in
  239.         SimpleXMLRPCRequestHandler.do_POST) but overriding the
  240.         existing method through subclassing is the prefered means
  241.         of changing method dispatch behavior.
  242.         '''
  243.         (params, method) = xmlrpclib.loads(data)
  244.         
  245.         try:
  246.             if dispatch_method is not None:
  247.                 response = dispatch_method(method, params)
  248.             else:
  249.                 response = self._dispatch(method, params)
  250.             response = (response,)
  251.             response = xmlrpclib.dumps(response, methodresponse = 1)
  252.         except Fault:
  253.             fault = None
  254.             response = xmlrpclib.dumps(fault)
  255.         except:
  256.             response = xmlrpclib.dumps(xmlrpclib.Fault(1, '%s:%s' % (sys.exc_type, sys.exc_value)))
  257.  
  258.         return response
  259.  
  260.     
  261.     def system_listMethods(self):
  262.         """system.listMethods() => ['add', 'subtract', 'multiple']
  263.  
  264.         Returns a list of the methods supported by the server."""
  265.         methods = self.funcs.keys()
  266.         if self.instance is not None:
  267.             if hasattr(self.instance, '_listMethods'):
  268.                 methods = remove_duplicates(methods + self.instance._listMethods())
  269.             elif not hasattr(self.instance, '_dispatch'):
  270.                 methods = remove_duplicates(methods + list_public_methods(self.instance))
  271.             
  272.         
  273.         methods.sort()
  274.         return methods
  275.  
  276.     
  277.     def system_methodSignature(self, method_name):
  278.         """system.methodSignature('add') => [double, int, int]
  279.  
  280.         Returns a list describing the signature of the method. In the
  281.         above example, the add method takes two integers as arguments
  282.         and returns a double result.
  283.  
  284.         This server does NOT support system.methodSignature."""
  285.         return 'signatures not supported'
  286.  
  287.     
  288.     def system_methodHelp(self, method_name):
  289.         '''system.methodHelp(\'add\') => "Adds two integers together"
  290.  
  291.         Returns a string containing documentation for the specified method.'''
  292.         method = None
  293.         if self.funcs.has_key(method_name):
  294.             method = self.funcs[method_name]
  295.         elif self.instance is not None:
  296.             None if hasattr(self.instance, '_methodHelp') else None<EXCEPTION MATCH>AttributeError
  297.         
  298.         if method is None:
  299.             return ''
  300.         else:
  301.             import pydoc as pydoc
  302.             return pydoc.getdoc(method)
  303.  
  304.     
  305.     def system_multicall(self, call_list):
  306.         """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => [[4], ...]
  307.  
  308.         Allows the caller to package multiple XML-RPC calls into a single
  309.         request.
  310.  
  311.         See http://www.xmlrpc.com/discuss/msgReader$1208
  312.         """
  313.         results = []
  314.         for call in call_list:
  315.             method_name = call['methodName']
  316.             params = call['params']
  317.             
  318.             try:
  319.                 results.append([
  320.                     self._dispatch(method_name, params)])
  321.             continue
  322.             except Fault:
  323.                 fault = None
  324.                 results.append({
  325.                     'faultCode': fault.faultCode,
  326.                     'faultString': fault.faultString })
  327.                 continue
  328.                 results.append({
  329.                     'faultCode': 1,
  330.                     'faultString': '%s:%s' % (sys.exc_type, sys.exc_value) })
  331.                 continue
  332.             
  333.  
  334.         
  335.         return results
  336.  
  337.     
  338.     def _dispatch(self, method, params):
  339.         """Dispatches the XML-RPC method.
  340.  
  341.         XML-RPC calls are forwarded to a registered function that
  342.         matches the called XML-RPC method name. If no such function
  343.         exists then the call is forwarded to the registered instance,
  344.         if available.
  345.  
  346.         If the registered instance has a _dispatch method then that
  347.         method will be called with the name of the XML-RPC method and
  348.         its parameters as a tuple
  349.         e.g. instance._dispatch('add',(2,3))
  350.  
  351.         If the registered instance does not have a _dispatch method
  352.         then the instance will be searched to find a matching method
  353.         and, if found, will be called.
  354.  
  355.         Methods beginning with an '_' are considered private and will
  356.         not be called.
  357.         """
  358.         func = None
  359.         
  360.         try:
  361.             func = self.funcs[method]
  362.         except KeyError:
  363.             if self.instance is not None:
  364.                 pass
  365.             None if hasattr(self.instance, '_dispatch') else None<EXCEPTION MATCH>AttributeError
  366.  
  367.         if func is not None:
  368.             return func(*params)
  369.         else:
  370.             raise Exception('method "%s" is not supported' % method)
  371.  
  372.  
  373.  
  374. class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  375.     '''Simple XML-RPC request handler class.
  376.  
  377.     Handles all HTTP POST requests and attempts to decode them as
  378.     XML-RPC requests.
  379.     '''
  380.     
  381.     def do_POST(self):
  382.         """Handles the HTTP POST request.
  383.  
  384.         Attempts to interpret all HTTP POST requests as XML-RPC calls,
  385.         which are forwarded to the server's _dispatch method for handling.
  386.         """
  387.         
  388.         try:
  389.             data = self.rfile.read(int(self.headers['content-length']))
  390.             response = self.server._marshaled_dispatch(data, getattr(self, '_dispatch', None))
  391.         except:
  392.             self.send_response(500)
  393.             self.end_headers()
  394.  
  395.         self.send_response(200)
  396.         self.send_header('Content-type', 'text/xml')
  397.         self.send_header('Content-length', str(len(response)))
  398.         self.end_headers()
  399.         self.wfile.write(response)
  400.         self.wfile.flush()
  401.         self.connection.shutdown(1)
  402.  
  403.     
  404.     def log_request(self, code = '-', size = '-'):
  405.         '''Selectively log an accepted request.'''
  406.         if self.server.logRequests:
  407.             BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size)
  408.         
  409.  
  410.  
  411.  
  412. class SimpleXMLRPCServer(SocketServer.TCPServer, SimpleXMLRPCDispatcher):
  413.     '''Simple XML-RPC server.
  414.  
  415.     Simple XML-RPC server that allows functions and a single instance
  416.     to be installed to handle requests. The default implementation
  417.     attempts to dispatch XML-RPC calls to the functions or instance
  418.     installed in the server. Override the _dispatch method inhereted
  419.     from SimpleXMLRPCDispatcher to change this behavior.
  420.     '''
  421.     
  422.     def __init__(self, addr, requestHandler = SimpleXMLRPCRequestHandler, logRequests = 1):
  423.         self.logRequests = logRequests
  424.         SimpleXMLRPCDispatcher.__init__(self)
  425.         SocketServer.TCPServer.__init__(self, addr, requestHandler)
  426.  
  427.  
  428.  
  429. class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
  430.     '''Simple handler for XML-RPC data passed through CGI.'''
  431.     
  432.     def __init__(self):
  433.         SimpleXMLRPCDispatcher.__init__(self)
  434.  
  435.     
  436.     def handle_xmlrpc(self, request_text):
  437.         '''Handle a single XML-RPC request'''
  438.         response = self._marshaled_dispatch(request_text)
  439.         print 'Content-Type: text/xml'
  440.         print 'Content-Length: %d' % len(response)
  441.         print 
  442.         sys.stdout.write(response)
  443.  
  444.     
  445.     def handle_get(self):
  446.         '''Handle a single HTTP GET request.
  447.  
  448.         Default implementation indicates an error because
  449.         XML-RPC uses the POST method.
  450.         '''
  451.         code = 400
  452.         (message, explain) = BaseHTTPServer.BaseHTTPRequestHandler.responses[code]
  453.         response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % {
  454.             'code': code,
  455.             'message': message,
  456.             'explain': explain }
  457.         print 'Status: %d %s' % (code, message)
  458.         print 'Content-Type: text/html'
  459.         print 'Content-Length: %d' % len(response)
  460.         print 
  461.         sys.stdout.write(response)
  462.  
  463.     
  464.     def handle_request(self, request_text = None):
  465.         '''Handle a single XML-RPC request passed through a CGI post method.
  466.  
  467.         If no XML data is given then it is read from stdin. The resulting
  468.         XML-RPC response is printed to stdout along with the correct HTTP
  469.         headers.
  470.         '''
  471.         if request_text is None and os.environ.get('REQUEST_METHOD', None) == 'GET':
  472.             self.handle_get()
  473.         elif request_text is None:
  474.             request_text = sys.stdin.read()
  475.         
  476.         self.handle_xmlrpc(request_text)
  477.  
  478.  
  479. if __name__ == '__main__':
  480.     server = SimpleXMLRPCServer(('localhost', 8000))
  481.     server.register_function(pow)
  482.     server.register_function((lambda x, y: x + y), 'add')
  483.     server.serve_forever()
  484.  
  485.